package cc.toprank.syncdatatask.listener;

import cc.toprank.syncdatatask.pojo.Merchant;
import cc.toprank.syncdatatask.pojo.MsgInfo;
import cc.toprank.syncdatatask.pojo.Organization;
import cc.toprank.syncdatatask.pojo.RshHandler;
import cc.toprank.syncdatatask.util.GlobalContants;
import com.alibaba.druid.util.StringUtils;
import com.alibaba.otter.canal.protocol.CanalEntry;
import com.toprank.druid.store.jdbc.SqlTemplate;
import com.toprank.druid.store.jdbc.builder.DeleteSql;
import com.toprank.druid.store.jdbc.builder.InsertSql;
import com.toprank.druid.store.jdbc.builder.SelectSql;
import com.toprank.druid.store.jdbc.builder.UpdateSql;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * description 订阅消息
 * User: WeiDa
 * Date: 2017-5-7
 * Time: 17:00
 */
public class SubscribeListener1 {
    @Autowired
    SqlTemplate sqlTemplate;

    private Logger logger = Logger.getLogger(SubscribeListener1.class);

    public void subscribe(MsgInfo msgInfo) throws Exception {
        try {
            if (msgInfo == null) return;
            if (!msgInfo.isFlag()) return;
            if(null == GlobalContants.ARCHIVE_ID || GlobalContants.ORG_ID.size()<1){
                Merchant merchant = initMerchant();
                initOrganization(String.valueOf(merchant.getOrgID()));
            }
            msgInfoHandler(msgInfo);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            return;
        }
    }

    public void subscribe2(MsgInfo msgInfo) throws Exception {
        try {
            if (msgInfo == null) return;
            if (!msgInfo.isFlag()) return;
            msgInfoHandler(msgInfo);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            return;
        }
    }

    public void msgInfoHandler(MsgInfo msgInfo) {
        try {
            List<CanalEntry.Column> data = msgInfo.getColumnList();

            logger.debug("客户端接收到来自服务端消息【" + msgInfo.getMsgId()+ "】成功");

            if (msgInfo.getEventType() == CanalEntry.EventType.INSERT) {
                //todo save
                insert(msgInfo.getTableName(), data);
                logger.info("save result:=====success");
            } else if (msgInfo.getEventType() == CanalEntry.EventType.UPDATE) {
                //todo update
                int result = update(msgInfo.getTableName(), msgInfo.getPrimaryKey(), msgInfo.getIdValue(), data);
                logger.info("update result:=====success:" + result);
            } else if (msgInfo.getEventType() == CanalEntry.EventType.DELETE) {
                //todo delete
                delete(msgInfo.getTableName(), msgInfo.getPrimaryKey(), msgInfo.getIdValue());
            } else if(msgInfo.getEventType() == CanalEntry.EventType.ALTER){
                //todo alter
                alter(msgInfo);
            }
            else if(msgInfo.getEventType() == CanalEntry.EventType.CREATE){
                //todo alter
                create(msgInfo);
            }else{
                logger.debug("客户端接收到来自服务端消息【" + msgInfo.toString() + "】成功,不做任何操作");
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getLocalizedMessage());
        } finally {
            return;
        }
    }


    private  void create(MsgInfo msgInfo){
        String sql = msgInfo.getSql();
        sql+=" AUTO_INCREMENT=";
        long autoValue = Long.valueOf(GlobalContants.ARCHIVE_ID.toString())*1000000000+4000000000L;
        sql += String.valueOf(autoValue);
        msgInfo.setSql(sql);
        alter(msgInfo);
    }

    private void alter(MsgInfo msgInfo){
        try {
            sqlTemplate.createTable(msgInfo.getSql());
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getCause());
            logger.error(e.getLocalizedMessage());
        }finally {
            return;
        }
    }

    private int delete(String tableName, String primaryKey, Object idValue) {

        try {
            DeleteSql deleteSql = new DeleteSql(sqlTemplate)
                    .delete()
                    .from()
                    .table(tableName)
                    .where(primaryKey + " = ?", idValue);
            return deleteSql
                    .doDelete();
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getCause());
            logger.error(e.getLocalizedMessage());
        } finally {
            return 0;
        }
    }

    /**
     * dazi
     *
     * @param tableName
     * @param primaryKey
     * @param idValue
     * @return
     */
    private int select(String tableName, String primaryKey, Object idValue) {
        SelectSql selectSql = new SelectSql(sqlTemplate);
        return selectSql.select()
                .columns("count(1)")
                .from()
                .table(tableName)
                .where(primaryKey + " = ?", idValue)
                .single();
    }

    /**
     * description 更新数据
     * User: WeiDa
     * Date: 2017-3-22
     * Time: 9:58
     */
    private int update(String tableName, String primaryKey, Object idValue, List<CanalEntry.Column> columnList) {
        try {
            String syncTime = "", syncTimeResult = "";
            UpdateSql updateSql = new UpdateSql(sqlTemplate);
            updateSql.update()
                    .table(tableName);
            for (CanalEntry.Column column : columnList) {

                if (column.getName().equalsIgnoreCase("SyncTime")) {
                    syncTime = column.getValue();
                    continue;
                }
                if (column.getName().equalsIgnoreCase("SyncTimeResult")) {
                    syncTimeResult = column.getValue();
                    continue;
                }
                if (column.getUpdated()) {
                    if (StringUtils.isEmpty(column.getValue())) {
                        updateSql.set(column.getName(), null);
                    }else{
                        if (column.getMysqlType().equalsIgnoreCase("bit(1)")) {//bit 类型 会报错 不处理的情况
                            updateSql.setOnNotNull(column.getName(), Integer.parseInt(column.getValue()));
                        }else{
                            updateSql.setOnNotNull(column.getName(), column.getValue());
                        }
                    }
                }
            }
            if (syncTime.equalsIgnoreCase(syncTimeResult)) return 0;
            LocalDateTime date = LocalDateTime.now();
            updateSql.setOnNotNull("SyncTime", date);
            updateSql.setOnNotNull("SyncTimeResult", date);
            int result = updateSql.where(primaryKey + " = ?", idValue)
                    .doUpdate();
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }finally {
            return 0;
        }
    }

    /**
     * description 插入新数据
     * User: WeiDa
     * Date: 2017-3-22
     * Time: 9:59
     */
    private void insert(String table, List<CanalEntry.Column> columnList) {
        try {
            String syncTime = "", syncTimeResult = "";
            List<String> keyList = new ArrayList<>();
            keyList.clear();
            List<Object> valueList = new ArrayList<>();
            valueList.clear();
            String orgId = "", parentId = "";
            for (CanalEntry.Column column : columnList) {
                if (StringUtils.isEmpty(column.getValue())) continue;
                if (column.getName().equalsIgnoreCase("IsSync")) continue;
                if (column.getName().equalsIgnoreCase("ArchiveID")) {
                    if (!column.getValue().equals(GlobalContants.ARCHIVE_ID.toString())) return;
                }
                if (column.getName().equalsIgnoreCase("OrgID")) {
                    //if(!column.getValue().equals(GlobalContants.ORG_ID.toString())) return;
                    orgId = column.getValue();
                }
                if (column.getName().equalsIgnoreCase("ParentID")) {
                    //if(!column.getValue().equals(GlobalContants.ORG_ID.toString())) return;
                    parentId = column.getValue();
                }
                if (column.getName().equalsIgnoreCase("SyncTime")) {
                    syncTime = column.getValue();
                    continue;
                }
                if (column.getName().equalsIgnoreCase("SyncTimeResult")) {
                    syncTimeResult = column.getValue();
                    continue;
                }
                keyList.add(column.getName());
                if (column.getMysqlType().equals("bit(1)")) {
                    valueList.add(Integer.parseInt(column.getValue()));
                }else if (column.getMysqlType().equalsIgnoreCase("bigint(20)") && StringUtils.isEmpty(column.getValue())) {
                    valueList.add(0);
                }else if (column.getMysqlType().equalsIgnoreCase("int(11)") && StringUtils.isEmpty(column.getValue())) {
                    valueList.add(0);
                }  else {
                    valueList.add(column.getValue());
                }
            }

            if (keyList.contains("OrgID") || keyList.contains("orgid") || keyList.contains("org_id")) {
                if (table.equalsIgnoreCase("U_OrganizationInfo")) {
                    if (GlobalContants.ORG_ID.contains(orgId) || GlobalContants.ORG_ID.contains(parentId)) {
                        GlobalContants.ORG_ID.add(orgId);
                        GlobalContants.ORG_ID.add(parentId);
                        logger.info("yes orgId:" + orgId);
                    } else {
                        return;
                    }
                } else {
                    if (GlobalContants.ORG_ID.contains(orgId)) {
                        logger.info("yes orgId:" + orgId);
                    } else {
                        return;
                    }
                }
            } else {
                logger.info("yes orgId:" + orgId);
            }

            if (syncTime.equalsIgnoreCase(syncTimeResult)) return;
            LocalDateTime date = LocalDateTime.now();
            keyList.add("SyncTime");
            keyList.add("SyncTimeResult");
            valueList.add(date);
            valueList.add(date);
            String[] str = new String[keyList.size()];
            InsertSql insertSql = new InsertSql(sqlTemplate)
                    .insert(table)
                    .columns(keyList.toArray(str)
                    );
            insertSql.values(valueList.toArray()
            );
            insertSql.doBatchInsert();
        } catch (NumberFormatException e) {
            e.printStackTrace();
            logger.error(e.getMessage());
            logger.error(e.getCause());
        }finally {
            return;
        }

    }


    private Merchant initMerchant(){
        Merchant merchant = selectClientInfo();
        if (null != merchant) {
            GlobalContants.ARCHIVE_ID = merchant.getArchiveID();
            GlobalContants.ORG_ID.add(String.valueOf(merchant.getOrgID()));
            logger.info("正确获取商家档案ID:" + merchant.toString());
            return merchant;
        }
        return null;
    }

    private void initOrganization(String orgID){
        List<Organization> list  =  selectOrganization(orgID);
        for(Organization organization : list){
            GlobalContants.ORG_ID.add(String.valueOf(organization.getOrgID()));
            if(null != organization && 0 != organization.getOrgID()){
                initOrganization(String.valueOf(organization.getOrgID()));
            }
            //GlobalContants.ORG_ID.add(String.valueOf(organization.getParentID()));
        }
    }

    public Merchant selectClientInfo() {
        SelectSql selectSql = new SelectSql(sqlTemplate);
        return selectSql.select()
                .columns("ArchiveID,OrgID")
                .from()
                .table("B_MerchantInfo").single(RshHandler.Merchant_RSH);
    }


    public List<Organization> selectOrganization(String orgID) {
        SelectSql selectSql = new SelectSql(sqlTemplate);
        return selectSql.select()
                .columns("ParentID,OrgID")
                .from()
                .table("U_OrganizationInfo")
                .where("ParentID = ?", orgID)
                .list(RshHandler.Organization_LIST_RSH);
    }

}
